//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Resource Application Block
//===============================================================================

using System;
using System.ComponentModel;
using System.Drawing.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Validation;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration.Design;
using EntLibContrib.Resource.Properties;

namespace EntLibContrib.Resource.Configuration.Design
{
  /// <summary>
  /// Represents a database resource provider.
  /// </summary>
  public sealed class DataResourceProviderNode : ResourceProviderBaseNode
	{
		#region Fields
		private ConnectionStringSettingsNode connectionStringSettingsNode;
		private EventHandler<ConfigurationNodeChangedEventArgs> onConnectionNodeRemoved;
		private EventHandler<ConfigurationNodeChangedEventArgs> onConnectionNodeRenamed;
		internal string connectionStringName;
		private string resourceBaseName;
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the database to use for the resources.
		/// </summary>
		/// <value>
		/// The database to use for the resources.
		/// </value>
		[Required]
		[Editor(typeof(ReferenceEditor), typeof(UITypeEditor))]
		[ReferenceType(typeof(ConnectionStringSettingsNode))]
		[ResourceCategory("CategoryProvider")]
		[ResourceDescription("DatabaseInstanceDescription")]
		public ConnectionStringSettingsNode DatabaseInstance
		{
			get { return connectionStringSettingsNode; }
			set
			{
				connectionStringSettingsNode = LinkNodeHelper.CreateReference<ConnectionStringSettingsNode>(connectionStringSettingsNode,
																																																		value,
																																																		onConnectionNodeRemoved,
																																																		onConnectionNodeRenamed);
				connectionStringName = (null == connectionStringSettingsNode) ? string.Empty : connectionStringSettingsNode.Name;
			}
		}

		/// <summary>
		/// Gets or sets the resource base name.
		/// </summary>
		/// <value>The resource base name.</value>
		[Required]
		[ResourceCategory("CategoryProvider")]
		[ResourceDescription("ResourceBaseNameDescription")]
		public string ResourceBaseName
		{
			get
			{
				return this.resourceBaseName;
			}
			set
			{
				if (value == null)
					this.resourceBaseName = String.Empty;
				else
					this.resourceBaseName = value.Trim();
			}
		}

		/// <summary>
		/// Gets a <see cref="DataResourceProviderData"/> configuration object using the node data.
		/// </summary>
		/// <value>
		/// A <see cref="DataResourceProviderData"/> configuration object using the node data.
		/// </value>
		[ReadOnly(true)]
		public override ResourceProviderDataBase ResourceProviderData
		{
			get { return new DataResourceProviderData(Name, connectionStringName, resourceBaseName); }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initialize a new instance of the <see cref="DataResourceProviderNode"/> class.
		/// </summary>
		public DataResourceProviderNode ()
			: this(new DataResourceProviderData(InternalResources.DefaultDataResourceProviderNodeName, string.Empty, string.Empty))
    {
    }

		/// <summary>
		/// Initialize a new instance of the <see cref="DataResourceProviderNode"/> class with a <see cref="DataResourceProviderData"/> configuration object.
		/// </summary>
		/// <param name="dataResourceProviderData">A <see cref="DataResourceProviderData"/> configuration object</param>
    public DataResourceProviderNode(DataResourceProviderData dataResourceProviderData) 
    {
			if (dataResourceProviderData == null)	throw new ArgumentNullException("dataResourceProviderData");

			Rename(dataResourceProviderData.Name);
			this.onConnectionNodeRemoved = new EventHandler<ConfigurationNodeChangedEventArgs>(OnConnectionStringSettingsNodeRemoved);
			this.onConnectionNodeRenamed = new EventHandler<ConfigurationNodeChangedEventArgs>(OnConnectionStringSettingsRenamed);
			this.connectionStringName = dataResourceProviderData.DatabaseInstanceName;
			this.resourceBaseName = dataResourceProviderData.ResourceBaseName;
		}
		#endregion

		#region Protected Methods
		/// <summary>
		/// Releases the unmanaged resources used by the <see cref="DataResourceProviderNode "/> and optionally releases the managed resources.
		/// </summary>
		/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
		protected override void Dispose (bool disposing)
		{
			try
			{
				if ( disposing )
				{
					if ( connectionStringSettingsNode != null )
					{
						connectionStringSettingsNode.Removed -= onConnectionNodeRemoved;
						connectionStringSettingsNode.Renamed -= onConnectionNodeRenamed;
					}
				}
			}
			finally
			{
				base.Dispose(disposing);
			}
		}
		#endregion

		#region Private Methods
		private void OnConnectionStringSettingsNodeRemoved (object sender, ConfigurationNodeChangedEventArgs e)
    {
      connectionStringSettingsNode = null;
    }

		private void OnConnectionStringSettingsRenamed(object sender, ConfigurationNodeChangedEventArgs e)
		{
			connectionStringName = e.Node.Name;
		}
		#endregion
	}
}